
; class JobQueue extends Queue: todo
(define (make-JobQueue self priority quantum)
	(let ((parent (make-Queue self)))
		(lambda (message)
			(case message
				((*quantum*)
					(lambda () quantum))
				((*priority*)
					(lambda () priority))
				(else (get-method message parent))))))

; class JobStat: todo
(define (make-JobStat self turnaround-time wait-time response-time)
	(lambda (message)
		(case message
			((*turnaround-time*)
				(lambda () turnaround-time))
			((*wait-time*)
				(lambda () wait-time))
			(else ()))))

; class Job: todo
(define (make-Job self id processes arrive-time job-stat finished) 
	(lambda (message)
		(case message
			(else ()))))

; get-ticks
(define (get-ticks time-slice) (% (get-timestamp) time-slice))

; round-robin
(define (round-robin job-queue)
	(let* ((quantum (ask job-queue *quantum*)) (tick (get-ticks quantum)))
		(do ((current-tick tick (get-ticks quantum)))
			*true*
			(if (eqv tick *zero*)
				(let* ((job (ask job-queue *dequeue*)) (finished (ask job *finished*)))
					(if (not finished)
						(begin (switch-to job)
							(ask job-queue *enqueue* job))))))))

; class MultiLevelFeedbackQueue
(define (make-MultiLevelFeedbackQueue self job-queues quantum boost-period current-queue)
	(define highest-priority-queue (vector-get job-queues 0))
	(define queue-size (vector-size job-queues))
	(define (transfer source-queue target-queue)
		(do ()
			(ask source-queue *is-empty*)
			(ask target-queue *enqueue* (ask source-queue *dequeue*))))
	(define (pick-job) (ask (vector-get job-queues current-queue) *dequeue*))
	(define (reduce-job-priority job)
		(if (eqv current-queue (- queue-size *one*))
			(ask (vector-get job-queues current-queue) *enqueue* job)
			(ask (vector-get job-queues (+ current-queue *one*)) *enqueue* job)))
	(lambda (message)
		(case message
			((*job-enter*)
				(lambda (job)
					(ask highest-priority-queue *enqueue* job)))
			((*boost*)
				(lambda ()
					(do ((q *zero* (+ q *one*)))
						(>= q queue-size)
						(transfer (vector-get job-queues q) highest-priority-queue))))
			((*ready-to-schedule*)
				(lambda ()
					(do ((q *zero* (+ q *one*)))
						(ask (vector-get job-queues q) *is-not-empty*)
						(begin (set! current-queue q)
							(eqv (get-ticks (ask (vector-get job-queues q) *quantum*)) *zero*)))))
			((*schedule*)
				(lambda ()
					(let ((job (pick-job)) (finished (ask job *finished*))
						(if (not finished)
							(begin (switch-to job)
								(reduce-job-priority job)))))))
			(else ()))))

; schedule-mlfq
(define (schedule-mlfq mlfq)
	(let* ((quantum (ask mlfq *quantum*)) (tick (get-ticks quantum))
		(boost-period (ask mlfq *boost-period*)) (boost-tick (get-ticks boost-period)))
		(do ((current-tick tick (get-ticks quantum)))
			*true*
			(if (eqv tick *zero*)
				(cond ((eqv boost-tick *zero*) (ask mlfq *boost*))
					((ask mlfq *ready-to-schedule*) (ask mlfq *schedule*))
					(else ()))))))


